QUIET=1

UNAME := $(shell uname -s)

ifneq (, $(findstring CYGWIN, ${UNAME}))
SEP := \;
else
SEP := :
endif

TARGET := ./target/classes
BUILD_TRIGGER := ${TARGET}/build
TESTS_OUTPUT := ${TARGET}/output
TESTS_FAILED := ${TARGET}/failed
$(shell touch ${TESTS_FAILED} )
LIB := ./lib
HAMCREST_JAR := ${LIB}/hamcrest-core-1.3.jar
JUNIT_JAR := ${LIB}/junit-4.11.jar
PREPARE := $(shell test -f ${TARGET} || mkdir -p ${TARGET})
PREPARE := $(shell test -f ${BUILD_TRIGGER} || touch -t 7001010000 ${BUILD_TRIGGER} )
JAVA_FILES := $(shell find ./src -name "*.java" ! -name "package-info.java" -newer ${BUILD_TRIGGER} | xargs)
RESOURCE_FILES := $(shell find ./src/test/resources -type f -newer ${BUILD_TRIGGER} | xargs)
CLASSPATH := ${HAMCREST_JAR}${SEP}${JUNIT_JAR}${SEP}${TARGET}
TESTS := $(shell find ./src -name "*.java" ! -name "package-info.java" -newer ${BUILD_TRIGGER} | sed -E 's/^.*src\/(main|test)\/java\///;s/\//\./g;s/(Test)?\.java/Test/' | cat - ${TESTS_FAILED} | sort | uniq | xargs )
DATETIME := $(shell date +%Y%m%d%H%M.%S)
JAVA_OPT := -Dfile.encoding=UTF-8
JAVAC_OPT :=

ifeq (run,$(firstword $(MAKECMDGOALS)))
RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
RUN_CLASS := $(shell echo ${RUN_ARGS} | sed -E 's/.*src\/(main|test)\/java\///;s/\//\./g;s/\.java//')
# turn RUN_ARGS target into nothing target
$(eval ${RUN_ARGS}:;@:)
$(eval .PHONY: build doc run ${RUN_ARGS})
endif

.PHONY: build doc run

all: test

resolve:
	@test -f ${JUNIT_JAR} || ant resolve

build: resolve
ifneq ($(strip ${JAVA_FILES}),)
	@echo "Compiling ... ${JAVA_FILES}" | sed -E 's/[^ \/]*\///g;s/\.java//g'
	@javac -encoding UTF-8 -cp ${CLASSPATH} -d ${TARGET} ${JAVAC_OPT} ${JAVA_FILES}
	@touch -t ${DATETIME} ${BUILD_TRIGGER}
endif
ifneq ($(strip ${RESOURCE_FILES}),)
	@echo "Copying resources"
	@cp -Rf ./src/test/resources/* ${TARGET}
	@touch -t ${DATETIME} ${BUILD_TRIGGER}
endif

test: build
ifeq (${QUIET}, 1)
	@echo "Testing ... ${TESTS}" | sed -E 's/[^ .]+\.//g'
	@java ${JAVA_OPT} -cp ${CLASSPATH} org.junit.runner.JUnitCore ${TESTS} | grep -v -E "at (org\.junit\.|java\.lang\.reflect\.|sun\.reflect)" 1> ${TESTS_OUTPUT}
	@grep -E "^([0-9]+\) |Could not find class)" ${TESTS_OUTPUT} | sed -E 's/^[0-9]+\) .*\(//;s/^Could not find class: //;s/\)//' | sort > ${TESTS_FAILED}
	@cat ${TESTS_OUTPUT} | sed -E 's/^[0-9]+\) ([^(]+)\(([^)]+)\)/Error \2:1:\1/;/^Error/s/\./\//g;s/^Error ([^:]*)/\.\/src\/test\/java\/\1\.java/' | grep -v -E "Could not find class"
else
	@echo "Testing ... in Verbose Mode."
	@java ${JAVA_OPT} -cp ${CLASSPATH} org.junit.runner.JUnitCore ${TESTS}
endif

run: build
	@echo "Running ... ${RUN_CLASS}"
	java ${JAVA_OPT} -cp ${CLASSPATH} ${RUN_CLASS}

clean:
	@rm -R ./target

doc:
	@ant -emacs javadoc

ctest:
	@bash tools/ctest


